﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Serialization;
using System.ServiceModel;
using System.ServiceModel.Web;
using System.Text;
using Microsoft.Practices.EnterpriseLibrary.Logging;
using MMITCore.TransactionActions;
using MMITCore.Logging;
using MMITCore.CurrencyConverter;
using MMITDomain;
using MMITDomain.Concrete;
using MMITDomain.Entities;
using MMITIntegration;
using System.Xml;
using System.Web.Security;
using System.ServiceModel.Channels;
using System.Web;
using System.Data;
namespace MMITCore
{
	
	public class CoreService : ICoreService, ICoreServiceREST
	{
        
		Actions actions =  new Actions() ;
		OTP otp = new OTP();
        MMITShared shared = new MMITShared();
		ResponseObject ro = new ResponseObject();
		SynkronLogger Log = new SynkronLogger("MMITCore");
		IEnumerable<Charge> charges;
		decimal? NetValue = 0;
		decimal? TotalCharge =0;
		Dictionary<string, object> d = new Dictionary<string, object>();

        
        public ResponseObject LoadMoney(string SerialNo, string PIN, int UserId)
		{
            try
            {
          
			//decimal? NetValue;
			//decimal? TotalCharge;
			//Check for Voucher
			//Voucher v = new Voucher();
			//v.SerialNo = SerialNo;
			//v.PIN = PIN;

            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port",  shared.OriginatingIP_Port(OperationContext.Current ));
            d.Add("Method :", "LoadMoney");
            Log.WriteInformation(446383, "Originating IP and Port", d);

			Voucher v = actions.IsVoucherValid( SerialNo, PIN);

			if (v == null || (bool)v.IsUsed)
			{
                if (v == null)
                {
                    v = new Voucher();
                    v.SerialNo = SerialNo;
                    v.PIN = PIN;                
                }

				ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
				ro.Description = "This Voucher Is Invalid , Please try another voucher";
				d.Clear();
				d.Add("Voucher Details ", Log.Desc(v));
				Log.WriteInformation(212, "Invalid Voucher PIN", d);
			}
			else
			{
				// Fetch Charges 
				
				Account UserAccount = actions.GetAccount(UserId);
				List<TransactionCharge> TxnCharges = new List<TransactionCharge>();
				int TT = int.MinValue;
				if (UserAccount != null || UserAccount.AccountTypeId != (int)AccountType.UnregisteredCustomer)
				{

					charges = actions.GetCharges((int)TransactionType.LoadVoucher, null, UserId);
					TT = (int)TransactionType.LoadVoucher;
				}
				else
				{
					ro.ResponseCode = (int)ResponseCodes.UnknownAccount;
					ro.Description = "Please Contact Customer Service or Try Again Later";
					Log.WriteInformation(6000001, "Unknown User Account, Id : " + UserId.ToString());
				}
				if (charges != null)
				{
					foreach (var c in charges)
					{
						if (c.FixedAmount != null)
						{
							// If Charge is a Fixed Amount
							TotalCharge += (decimal)c.FixedAmount;
							Log.WriteInformation(216, "charge for TransactionType=" + TT.ToString() + ", charge value = " + c.FixedAmount.ToString());
							TransactionCharge t = new TransactionCharge();
							t.Amount = c.FixedAmount;
							t.ChargeId = c.Id;
							t.CreditPartyId = 1;
							t.DebitPartyId = UserId;
							TxnCharges.Add(t);
						}
						if (c.PercentageAmount != null)
						{
							//If Charge is a Percentage Amount
							TotalCharge += ((decimal)c.PercentageAmount * v.Value) / 100;
							Log.WriteInformation(217, "charge for TransactionType=" + TT.ToString() + ", charge value = " + ((c.PercentageAmount * v.Value) / 100).ToString());
							TransactionCharge t = new TransactionCharge();
							t.Amount = ((decimal)c.PercentageAmount * v.Value) / 100;
							t.ChargeId = c.Id;
							t.CreditPartyId = 1;
							t.DebitPartyId = UserId;
							TxnCharges.Add(t);
						}

					}

				}
				else
				{
					// Log No charges to this Transaction
					Log.WriteInformation(215, "No charges for TransactionType: " + TransactionType.LoadVoucher.ToString());

				}
				NetValue = v.Value - TotalCharge;
				if (NetValue > 0)
				{
					ro = actions.CheckRules(TT, UserId, "Recipient", v.Value);
				}
				else
				{
					ro.ResponseCode = (int)ResponseCodes.NegativeTransactionValue;
					ro.Description = "The Charges Assigned to this Transaction Exceed your Voucher Value, Please purchase a voucher with the proper Value";
					Log.WriteInformation(218, "Used Voucher PIN" + v.PIN + ", SerialNo : " + v.SerialNo + " by UserId =" + UserId.ToString());
				}
				if (ro.ResponseCode == 10)
				{
					Transaction t = new Transaction();

					t.SenderId = UserId;
					t.RecipientId = UserId;
					t.Amount = NetValue;
					t.TimeInitiated = DateTime.Now;
					t.LastUpdate = DateTime.Now;
					t.Status = (int)TransactionStatuses.Completed;
					t.TransactionTypeId = TT;                   
					t.AuthorisationId = null;
					t.TransactionCode = otp.Generate();

					t = actions.AddTransaction(t, TxnCharges);

					if (t.Id != 0)
					{
						//Update the Voucher to IsUsed
						//Voucher vo = new Voucher();

						//vo.Id = v.Id;
						//vo.DateGenerated = v.DateGenerated;
						//vo.PIN = v.PIN;
						//vo.Value = v.Value;
						//vo.SerialNo = v.SerialNo;
						//vo.IsUsed = true;
						//vo.TransactionId = t.Id;
						//vo.DateUsed = DateTime.Now;

						v.IsUsed = true;
						v.TransactionId = t.Id;
						v.DateUsed = DateTime.Now;

						actions.InvalidateVoucher(v);

						ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
						ro.Description = "Voucher Successfully Loaded";
						ro.TransactionCode = t.TransactionCode;
						Log.WriteInformation(61185219, "Transaction Successful, PIN: " + v.PIN + ", SerialNo : " + v.SerialNo + " by UserId =" + UserId.ToString() );

					}


				}
			  
			
			}

			
            }
            catch (Exception e)
            {
                Log.WriteCritical(67321, e);
                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please contact MMIT Customer Service.";
                
            }
            return ro;
		}

		public ResponseObject LoadMoneyExternal(string UkashVoucherNumber, int UserId, decimal Amount, string Currency)
		{
             try
            {
          
            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
            d.Add("Method :", "LoadMoneyExternal");
            Log.WriteInformation(446384, "Originating IP and Port", d);

			//long check = 0;

			if (UkashVoucherNumber.Length != 19 || Actions.IsNumeric(UkashVoucherNumber) != true)
			{
				ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
				ro.Description = "This Ukash Voucher Is Invalid , Please try another voucher";
				d.Clear();
				d.Add("Voucher Details ", UkashVoucherNumber);
				d.Add("Account ", UserId);
				Log.WriteInformation(21756462, "Invalid Ukash Voucher ", d);
				return ro;
			}
			// Fetch Charges 

			Account UserAccount = actions.GetAccount(UserId);

			List<TransactionCharge> TxnCharges = new List<TransactionCharge>();
			int TT = int.MinValue;
			if (UserAccount != null || UserAccount.AccountTypeId != (int)AccountType.UnregisteredCustomer)
			{

				charges = actions.GetCharges((int)TransactionType.LoadVoucher, null, UserId);
				TT = (int)TransactionType.LoadVoucher;
			}
			else
			{
				ro.ResponseCode = (int)ResponseCodes.UnknownAccount;
				ro.Description = "Please Contact Customer Service or Try Again Later";
				Log.WriteInformation(6000001, "Unknown User Account, Id : " + UserId.ToString());
			}


			// Connect to Google Exchange API
			//decimal ConveretedAmount = ExchangeRateCalculator.Convert(Amount, Currency, "NGN");

			if (charges != null)
			{
				foreach (var c in charges)
				{
					if (c.FixedAmount != null)
					{
						// If Charge is a Fixed Amount
						TotalCharge += (decimal)c.FixedAmount;
						Log.WriteInformation(216, "charge for TransactionType=" + TT.ToString() + ", charge value = " + c.FixedAmount.ToString());
						TransactionCharge t = new TransactionCharge();
						t.Amount = c.FixedAmount;
						t.ChargeId = c.Id;
						t.CreditPartyId = 1;
						t.DebitPartyId = UserId;
						TxnCharges.Add(t);
					}
					if (c.PercentageAmount != null)
					{
						//If Charge is a Percentage Amount
						TotalCharge += ((decimal)c.PercentageAmount * Amount) / 100;
						Log.WriteInformation(217, "charge for TransactionType=" + TT.ToString() + ", charge value = " + ((c.PercentageAmount * Amount) / 100).ToString());
						TransactionCharge t = new TransactionCharge();
						t.Amount = ((decimal)c.PercentageAmount * Amount) / 100;
						t.ChargeId = c.Id;
						t.CreditPartyId = 1;
						t.DebitPartyId = UserId;
						TxnCharges.Add(t);
					}

				}

			}
			else
			{
				// Log No charges to this Transaction
				Log.WriteInformation(215, "No charges for TransactionType: " + TransactionType.LoadVoucher.ToString());

			}
			
			NetValue = Amount - TotalCharge;
			if (NetValue > 0)
			{
				ro = actions.CheckRules(TT, UserId, "Recipient", Amount);
			}
			else
			{
				ro.ResponseCode = (int)ResponseCodes.NegativeTransactionValue;
				ro.Description = "The Charges Assigned to this Transaction Exceed your Voucher Value, Please purchase a voucher with the proper Value";
				Log.WriteInformation(218, "Used Voucher PIN" + UkashVoucherNumber +  " by UserId =" + UserId.ToString());
			}



			UkashIntegration ui = new UkashIntegration();
			IntegrationResponse ir = ui.RedeemUkash(Amount, UkashVoucherNumber, Currency,0);

			switch (ir.TransactionCode)
			{
				case "0" :
					ro.ResponseCode = 10;
					Transaction t = new Transaction();
					t.SenderId = UserId;
					t.RecipientId = UserId;
					t.Amount = NetValue;
					t.TimeInitiated = DateTime.Now;
					t.LastUpdate = DateTime.Now;
					t.Status = (int)TransactionStatuses.Completed;
					t.TransactionTypeId = TT;
					t.AuthorisationId = null;
					t.TransactionCode = ir.IntegrationTransactionCode;

					t = actions.AddTransaction(t, TxnCharges);

					if (t.Id != 0)
					{									 
						ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
						ro.Description = "Voucher Successfully Loaded";
						ro.TransactionCode = t.TransactionCode;
						Log.WriteInformation(61185219, "Transaction Successful, Voucher Number: " + UkashVoucherNumber +  " by UserId =" + UserId.ToString());

					}
					break;
				case "1" :
					ro.ResponseCode = Convert.ToInt32(ir.TransactionCode);
					ro.Description = "Transaction was Declined, Please Contact Customer Service";
                    
                    Log.WriteInformation(61185221, "Transaction Declined, Voucher Number: " + UkashVoucherNumber +  " by UserId =" + UserId.ToString());
					break;
				default:
					ro.ResponseCode = Convert.ToInt32(ir.TransactionCode);
					ro.Description = ir.errDescription;

                    Log.WriteInformation(61185222, "Transaction Failed, Voucher Number: " + UkashVoucherNumber + " by UserId =" + UserId.ToString());
					break;
			
			}


            }
             catch (Exception e)
             {
                 Log.WriteCritical(67322, e);
                 ro.ResponseCode = (int)ResponseCodes.SystemError;
                 ro.Description = "Please contact MMIT Customer Service.";
                 
             }
             return ro;
		}

        public ResponseObject SendMoney(string SerialNo, string PIN, int SenderId, int RecipientId, string RecipientMSISDN, decimal Amount, string FirstName, 
            string LastName, int IdenticationTypeId, string IdentificationNumber, int CountryId, int RecipientType, int PartnerId)
		{

            try
            {
                //Add logging of where request originates from
                d.Clear();
                d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
                d.Add("Method :", "SendMoney");
                Log.WriteInformation(446385, "Originating IP and Port", d);


                Voucher v;
                if (SerialNo != null || PIN != null)
                {
                    //Check for Voucher
                    // v.SerialNo = SerialNo;
                    // v.PIN = PIN;
                    v = actions.IsVoucherValid(SerialNo, PIN);
                    if (v == null || (bool)v.IsUsed)
                    {
                        ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
                        ro.Description = "This Voucher Is Invalid , Please try another voucher";
                        d.Clear();
                        d.Add("Voucher Details ", Log.Desc(v));
                        Log.WriteInformation(212, "Invalid Voucher PIN", d);
                        return ro;
                    }
                    switch (v.IsUsed)
                    {
                        case false:
                            // this Is for if the Voucher is sent along 
                            ro = LoadMoney(SerialNo, PIN, SenderId);
                            break;
                        case true:
                            ro.ResponseCode = (int)ResponseCodes.UsedVoucher;
                            ro.Description = "This Voucher Has Been Used, Please try another voucher";
                            Log.WriteInformation(211, "Used Voucher PIN" + v.PIN + ", SerialNo : " + v.SerialNo + " by UserId =" + SenderId.ToString());
                            return ro;

                        default:
                            if (v.SerialNo == "Exception")
                            {
                                ro.ResponseCode = (int)ResponseCodes.SystemError;
                                ro.Description = "Please Contact Customer Service or Try Again Later";
                                return ro;
                            }

                            break;

                    }

                }

                Account RecipientAccount = new Account();
                switch (RecipientType)
                {
                    case 1: //MMIT Recipient                   
                        if (RecipientId == 0)
                        {
                            RecipientAccount = actions.GetAccount(RecipientMSISDN);
                        }
                        else
                        {
                            RecipientAccount = actions.GetAccount(RecipientId);
                        }
                        break;
                    case 2: //Mobipay Recipient . should we create an account for Mobipay recipients ????????
                        Partner p = new Partner();
                        p.Id = PartnerId;
                        RecipientAccount = actions.GetAccount(p);
                        break;
                    default:

                        break;
                }





                List<TransactionCharge> TxnCharges = new List<TransactionCharge>();
                int TT=0;
                if (RecipientAccount == null || RecipientAccount.AccountTypeId == (int)AccountType.UnregisteredCustomer)
                {
                    charges = actions.GetCharges((int)TransactionType.P2PUnregistered, null, SenderId);
                    TT = (int)TransactionType.P2PUnregistered;
                }
                else
                {
                    switch (RecipientType)
                    {
                        case 1:
                            charges = actions.GetCharges((int)TransactionType.P2PRegistered, null, SenderId);
                            TT = (int)TransactionType.P2PRegistered;
                            break;
                        case 2:
                            charges = actions.GetCharges((int)TransactionType.P2PExternal, null, SenderId);
                            TT = (int)TransactionType.P2PExternal;
                            break;
                        default:
                            break;

                    }

                    if (charges != null)
                    {
                        foreach (var c in charges)
                        {
                            if (c.FixedAmount != null)
                            {
                                // If Charge is a Fixed Amount
                                TotalCharge += (decimal)c.FixedAmount;
                                Log.WriteInformation(216, "charge for TransactionType=" + TT.ToString() + ", charge value = " + c.FixedAmount.ToString());
                                TransactionCharge t = new TransactionCharge();
                                t.Amount = c.FixedAmount;
                                t.ChargeId = c.Id;
                                TxnCharges.Add(t);
                            }
                            else
                            {
                                //If Charge is a Percentage Amount
                                TotalCharge += ((decimal)c.PercentageAmount * Amount) / 100;
                                Log.WriteInformation(217, "charge for TransactionType=" + TT.ToString() + ", charge value = " + c.FixedAmount.ToString());
                                TransactionCharge t = new TransactionCharge();
                                t.Amount = ((decimal)c.PercentageAmount * Amount) / 100;
                                t.ChargeId = c.Id;
                                TxnCharges.Add(t);
                            }

                        }

                    }
                    else
                    {
                        // Log No charges to this Transaction
                        Log.WriteInformation(215, "No charges for TransactionType");

                    }

                    NetValue = Amount - TotalCharge;


                    if (NetValue > 0)
                    {
                        // Check the Transaction Details against the Rules
                        // Create transaction and debit/credit parties
                        switch (TT)
                        {
                            case 1:
                                break;
                            case 2:
                            case 11:
                                ro = actions.CheckRules(TT, SenderId, "Sender", Amount);
                                if (ro.ResponseCode == 10)
                                {
                                    if (RecipientAccount != null || RecipientAccount.AccountTypeId != 0)
                                    {
                                        ro = actions.CheckRules(TT, RecipientAccount.Id, "Recipient", Amount);
                                    }
                                    //Commenting this out with the assumption that a new recipient will not have been a party to a txn before
                                    //else
                                    //{

                                    //    ro = actions.CheckRules(TT, SenderId, "New Recipient", v.Value);
                                    //}
                                }

                                break;
                            case 3:

                                break;
                            default:

                                break;
                        }

                        if (ro.ResponseCode == 10)
                        {


                            Transaction t = new Transaction();

                            if (RecipientAccount == null)
                            {

                                Customer c = new Customer();
                                c.Mobile = RecipientMSISDN;
                                c.Firstname = FirstName;
                                c.Lastname = LastName;
                                c.IdentificationTypeId = 1;// Defaulting to Passport This needs review 
                                c.IdentificationNumber = IdentificationNumber;
                                if (CountryId == 0)
                                {
                                    c.CountryId = 150;
                                }
                                else
                                {
                                    c.CountryId = CountryId;
                                }

                                RecipientAccount = actions.AddCustomerAndAccount(c, true);

                                //Add customer and account  to DB and return customerId                   
                            }

                            // Add account to DB and return account Id
                            // Create Transaction
                            t.SenderId = SenderId;
                            t.RecipientId =  RecipientAccount.Id;
                            t.Amount = NetValue;
                            t.TimeInitiated = DateTime.Now;
                            t.LastUpdate = DateTime.Now;
                            t.Status = (int)TransactionStatuses.Initiated;
                            t.TransactionTypeId = TT;
                            t.TransactionCode = "MMITSM-" + otp.Generate();
                            t.AuthorisationId = null;


                            if (TxnCharges.Count > 0)
                            {
                                List<TransactionCharge> TCharges = new List<TransactionCharge>();
                                foreach (TransactionCharge r in TxnCharges)
                                {
                                    //If Charges Apply set TransactionCharge Properties Here  
                                    r.CreditPartyId = 1; //MTO or Scheme Runner
                                    r.DebitPartyId = SenderId;
                                    TCharges.Add(r);

                                }
                                TxnCharges = TCharges;

                            }
                            switch (RecipientType)
                            { 
                                case 2 :// Call Mobipay Integration and send the Transaction
                                    Customer c = actions.GetCustomer(SenderId , 0);
                                    MobiPayIntegration mo = new MobiPayIntegration();
                                    IntegrationResponse ir = mo.SendMoneyToMobiPayCustomer(FirstName + " " + LastName, RecipientMSISDN, c.Firstname + " " + c.Lastname, c.Mobile, NetValue, t.TransactionCode);
                                    if (ir.IntegrationTransactionCode == "111")
                                    {
                                        ro.Description = ir.txtDescription;
                                        t.TimeFinalised = DateTime.Now;
                                       
                                        
                                        
                                    }
                                    else
                                    {
                                        Log.WriteCritical(901, "Mobipay Down");
                                        ro.ResponseCode = (int)ResponseCodes.SystemError;
                                        ro.Description = "Please Contact Customer Service";
                                        ro.Description += ir.txtDescription;
                                        return ro;                                   
                                    }                               
                                                             
                                    break;
                                default :
                                    break;
                            
                            }


                            t = actions.AddTransaction(t, TxnCharges);

                            ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
                            ro.Description += "The Recipient has been notified of the Money Sent, Please Contact  Them with One Time Transaction Code Sent to Your Mobile";
                            ro.TransactionCode = t.TransactionCode;
                            d.Clear();
                            d.Add("Transaction : ", Log.Desc(t));
                            Log.WriteInformation(219, "Transaction Successful, PIN: " + PIN + ", SerialNo : " + SerialNo + " by UserId =" + SenderId.ToString() + " to " + RecipientAccount.Id.ToString(), d);


                        }
                        else
                        {
                            return ro;
                        }


                    }
                    else
                    {
                        ro.ResponseCode = (int)ResponseCodes.NegativeTransactionValue;
                        ro.Description = "The Charges Assigned to this Transaction Exceed your Transaction Amount, Please Contact Customer Service";
                        Log.WriteInformation(218, "Charges are Higher than Transaction Value " + " by Sender ID =" + SenderId.ToString() + System.Environment.NewLine + "Total Charge : " + TotalCharge.ToString() + System.Environment.NewLine + "; Transaction Amount : " + Amount.ToString());
                    }

                }
            }
            catch (Exception e)
            {
                Log.WriteCritical(901, e);

                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please Contact Customer Service";
            }
		 return ro;
		}

        //public ResponseObject SendMoneyExternal(int SenderId, string RecipientMSISDN, decimal Amount, string FirstName, string LastName, int IdenticationTypeId, string IdentificationNumber, int recipientCountryId, string Address, int SendMoneyRecipientType)
        //{
        //    try
        //    {
        //        //Add logging of where request originates from
        //        d.Clear();
        //        d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
        //        Log.WriteInformation(446385, "Originating IP and Port", d);


        //    }
        //    catch (Exception ex)
        //    {
        //        Log.WriteCritical(905651, ex.InnerException);
        //        ro.ResponseCode = (int)ResponseCodes.SystemError;
        //        ro.Description = "Please Contact Customer Service";
            
        //    }

        //    return ro;
        
        //}
 		
		public ResponseObject WithdrawMoney(string token, decimal amount, string RecipientMSISDN, int AuthorisationId)
		{
              try
		  {
            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
            d.Add("Method :", "WithdrawMoney");
            Log.WriteInformation(446386, "Originating IP and Port", d);

			Transaction t = actions.CheckTransaction(token);
			if (t != null)
			{
				switch (t.Status)
				{
					case (int)TransactionStatuses.Pending:                        
						d.Clear();
						d.Add("Valid Transaction for Withdrawal", Log.Desc(t));
						Log.WriteInformation(643453822, "Valid Transaction", d);
						Account UserAccount = actions.GetAccount(RecipientMSISDN);
						actions.ChangeTransactionState(t.Id, (int)TransactionStatuses.Completed, UserAccount.Id, t.TransactionTypeId);
						ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
						ro.Description = "Transaction Withdrawal Completed";
						break;

					default:
						ro.ResponseCode = (int)ResponseCodes.SystemError;
						ro.Description = "This Transaction is in an Invalid State";
						d.Clear();
						d.Add("Flouted Rule ", Log.Desc(t));
						Log.WriteInformation(643453222, "Fraud Suspected", d);

						break;



				}
			}
			else
			{
				ro.ResponseCode = (int)ResponseCodes.TransactionNotFound;
				ro.Description = "Transaction Does Not Exist ";
				d.Clear();
				d.Add("Invalid Token ", token);
				Log.WriteInformation(643123222, "Non Existent Transaction", d);
			
			}

          }
              catch (Exception e)
              {
                  Log.WriteCritical(902, e);

                  ro.ResponseCode = (int)ResponseCodes.SystemError;
                  ro.Description = "Please Contact Customer Service";
              }
              return ro;
		}

		public ResponseObject RequestToken(decimal amount, string MSISDN)
		{
            try
            {

            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
            d.Add("Method :", "RequestToken");
            Log.WriteInformation(446387,  "Originating IP and Port", d);


			Account a = actions.GetAccount(MSISDN);

			ro = actions.ReserveMoneyandFetchToken(amount, a.Id, (int)TransactionType.WithdrawMoney);
			// Put in code to deliver Transaction code . SMS??

            }
            catch (Exception e)
            {
                Log.WriteCritical(903, e);

                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please Contact Customer Service";
            }
            return ro;
		}

		//Not Completed Yet
		public RedeemVoucher  RedeemVoucher(string SerialNo, string PIN, string Username, string Password, string TransactionCode, int VoucherType, decimal Amount, decimal PurchaseValue, string Currency , string MobileNo)
		{
            RedeemVoucher rv = new MMITCore.RedeemVoucher();
            IntegrationResponse ir = new IntegrationResponse();
            try
            {
            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
            d.Add("Method :", "RedeemVoucher");
            Log.WriteInformation(446388, "Originating IP and Port", d);


           
            // Check if purchase value greater than amount
           
            
            if (Membership.ValidateUser(Username, Password))
            {
               d.Add("Username ", Username);
               Log.WriteInformation(4533455, "User Authenticated Successfully", d);

                if (!Roles.IsUserInRole(Username, "Partner"))
                {
                    ro.ResponseCode = (int)ResponseCodes.SystemError;
                    ro.Description = "Please Contact MMIT, You do not have access to perform this transaction";
                    rv.ro = ro;
                    d.Clear();
                    d.Add("Username", Username);
                    d.Add("Role", "Partner");
                    Log.WriteError(21776462, "Partner does not have the Partner Role ", d);
                    return rv;
                
                }

                  //Check for Partner
                            Partner p = actions.GetPartner(Username);
                            if (p == null)
                            {
                                ro.ResponseCode = (int)ResponseCodes.SystemError;
                                ro.Description = "Please Contact MMIT";
                                rv.ro = ro;
                                d.Clear();
                                d.Add("Username", Username);
                                Log.WriteError(21756462, "Customer with this username not found ", d);
                            }
                            else
                            {
                                // if customer exists check for their account
                                Account UserAccount = actions.GetAccount(p);
                                if (UserAccount == null)
                                {
                                    ro.ResponseCode = (int)ResponseCodes.SystemError;
                                    ro.Description = "Please Contact MMIT";
                                    rv.ro = ro;
                                    d.Clear();
                                    d.Add("Username", Username);
                                    Log.WriteError(217565462, "Account  with this username not found ", d);
                                }
                                else
                                {
                                    // check voucher type and carry out appropriate action
                                    Voucher nv = new Voucher();
                                    Transaction t = new Transaction();


                                    switch (VoucherType)
                                    {
                                        case 1:
                                            if (PurchaseValue > Amount)
                                            {
                                                ro.ResponseCode = (int)ResponseCodes.InvalidTransaction;
                                                ro.Description = "The Amount to be paid for must not be more than the Voucher Value ";
                                                d.Clear();
                                                d.Add("Purchase Value", PurchaseValue.ToString());
                                                d.Add("Voucher Value", Amount.ToString());
                                                Log.WriteError(21795462, " The Amount to be paid for must not be more than the Voucher Value ", d);
                                                rv.ro = ro;
                                                return rv;

                                            }
                                            if (PIN.Length != 19 || Actions.IsNumeric(PIN) != true)
                                            {
                                                ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
                                                ro.Description = "This Ukash Voucher Is Invalid , Please try another voucher";
                                                rv.ro = ro;
                                                d.Clear();
                                                d.Add("Voucher Details ", PIN);
                                                d.Add("Partner Username", Username);
                                                Log.WriteInformation(21756462, "Invalid Ukash Voucher ", d);
                                            }
                                            else
                                            {
                                               
                                                // make call to ukash
                                                UkashIntegration ui = new UkashIntegration();
                                                ir = ui.RedeemUkash(Amount, PIN , Currency, PurchaseValue  );

                                               
                                                t.TransactionTypeId = (int)TransactionType.RedeemVoucher;
                                                t.SenderId = UserAccount.Id;
                                                t.RecipientId = UserAccount.Id;
                                                t.Amount = PurchaseValue;
                                                t.TimeInitiated = DateTime.Now;
                                                t.LastUpdate = DateTime.Now;                                               
                                                t.AuthorisationId = null;
                                                t.TransactionCode = TransactionCode;


                                               

                                               //add check around the ir response 

                                                switch (ir.TransactionCode)
                                                {
                                                    case "0":
                                                        t.Status = (int)TransactionStatuses.Completed;

                                                        if (ir.UO.ChangeIssueVoucherNumber != "")
                                                        {
                                                            //create a new voucher
                                                            nv.PIN = ir.UO.ChangeIssueVoucherNumber;
                                                            nv.Value = Convert .ToDecimal ( ir.UO.ChangeIssueAmount);
                                                            rv.NewVoucher = nv;
                                                        }

                                                       
                                                            ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
                                                            ro.Description = "Voucher Successfully Loaded and New Voucher Generated";
                                                            ro.TransactionCode = t.TransactionCode;
                                                            Log.WriteInformation(61285219, "Transaction Successful, Voucher Number: " + PIN + " by UserId =" + UserAccount.Id.ToString());

                                                        
                                                        break;
                                                    case "1":
                                                        t.Status = (int)TransactionStatuses.Denied;
                                                        ro.ResponseCode = Convert.ToInt32(ir.TransactionCode);
                                                        ro.Description = "Transaction was Declined, Please Contact Customer Service";
                                                        break;
                                                    default:
                                                        t.Status = (int)TransactionStatuses.Cancelled;
                                                        ro.ResponseCode = Convert.ToInt32(ir.TransactionCode);
                                                        ro.Description = ir.errDescription;
                                                        break;

                                                }

                                                // save transaction and add response object to redeem voucher object
                                                t = actions.AddTransaction(t);
                                                rv.ro = ro;

                                            }
                                            break;
                                        case 2:
                                           
                                            Voucher v = actions.IsVoucherValid(SerialNo, PIN);
                                           
                                                t.TransactionTypeId = (int)TransactionType.RedeemVoucher;
                                                t.SenderId = UserAccount.Id;
                                                t.RecipientId = UserAccount.Id;
                                                t.Amount = PurchaseValue ;
                                                t.TimeInitiated = DateTime.Now;
                                                t.LastUpdate = DateTime.Now;                                               
                                                t.AuthorisationId = null;
                                                t.TransactionCode = TransactionCode+ "-" + VoucherType.ToString();;
                                               

                                            if (v.PIN == null || (bool)v.IsUsed)
                                            {
                                                ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
                                                ro.Description = "This Voucher Is Invalid , Please try another voucher";
                                                rv.ro = ro;
                                                d.Clear();
                                                d.Add("Serial No", v.SerialNo);
                                                d.Add("PIN", v.PIN);
                                                d.Add("Value", v.Value.ToString());
                                                d.Add("Voucher Details ", Log.Desc(v));
                                                Log.WriteInformation(3466546, "Invalid Voucher PIN", d);
                                                t.Status = (int)TransactionStatuses.Cancelled;
                                                // add transaction
                                                t = actions.AddTransaction(t);
                                            }
                                            else
                                            {
                                                // Check if purchase value greater than amount
                                                if (PurchaseValue > v.Value)
                                                {
                                                    ro.ResponseCode = (int)ResponseCodes.InvalidTransaction;
                                                    ro.Description = "The Amount to be paid for must not be more than the Voucher Value ";
                                                    d.Clear();
                                                    d.Add("Purchase Value", PurchaseValue.ToString());
                                                    d.Add("Voucher Value", v.Value .ToString());
                                                    Log.WriteError(217575462, " The Amount to be paid for must not be more than the Voucher Value ", d);
                                                    rv.ro = ro;
                                                    return rv;

                                                }
                                                d.Add("Serial No", v.SerialNo);
                                                d.Add("PIN", v.PIN);
                                                d.Add("Value", v.Value.ToString());
                                                d.Add("Voucher Details ", Log.Desc(v));
                                                Log.WriteInformation(34622546, "Valid Voucher PIN", d);

                                                //complete transaction                                              
                                                t.Status = (int)TransactionStatuses.Completed;
                                             

                                                // add transaction
                                                t = actions.AddTransaction(t);

                                                v.TransactionId = t.Id;
                                                v.DateUsed = DateTime.Now;

                                                //invalidate old voucher 
                                                actions.InvalidateVoucher(v);
                                               
                                                ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
                                                ro.Description = "Voucher Successfully Loaded";

                                                //create new voucher if there is change between amount and value of the voucher
                                                if (v.Value >PurchaseValue )
                                                {

                                                    nv.Value = v.Value - PurchaseValue;
                                                    nv.PIN = otp.Generate(10);
                                                    nv.SerialNo = p.Name.ToUpper() +otp.Generate(8);
                                                    nv.GeneratedBy = UserAccount.Id;
                                                    nv.ParentId = v.Id;
                                                    nv.IsUsed = false;
                                                    nv.DateGenerated = DateTime.Now;

                                                    actions.AddVoucher(nv);

                                                    // add the new voucher to the response details 

                                                    rv.NewVoucher = nv;

                                                    d.Clear();
                                                    d.Add("Serial No", nv.SerialNo );
                                                    d.Add("PIN", nv.PIN );
                                                    d.Add("Value", nv.Value.ToString());
                                                    d.Add("Voucher Details ", Log.Desc(v));
                                                    Log.WriteInformation(3466546, "New Voucher Generated", d);

                                                    ro.Description = "Voucher Successfully Loaded and New Voucher Generated";   
                                                }                                             

                                            }

                                          

                                            break;
                                        case 3:
                                            // Logic to Handle Mobipay Vouchers
                                            if (MobileNo == null)
                                            {
                                                t.Status = (int)TransactionStatuses.Denied;
                                                ro.ResponseCode = 0;
                                                ro.Description = "Mobile Number must not be null";
                                                rv.ro = ro;
                                                return rv;
                                            }
                                            MobiPayIntegration mi = new MobiPayIntegration();
                                            ir = mi.RedeemMobiPay(PIN, (long)PurchaseValue, Currency, MobileNo);
                                            
                                                t.TransactionTypeId = (int)TransactionType.RedeemVoucher;
                                                t.SenderId = UserAccount.Id;
                                                t.RecipientId = UserAccount.Id;
                                                t.Amount = PurchaseValue;
                                                t.TimeInitiated = DateTime.Now;
                                                t.LastUpdate = DateTime.Now;                                               
                                                t.AuthorisationId = null;
                                                t.TransactionCode = TransactionCode + "-" + VoucherType.ToString();

                                                //add check around the ir response 

                                                switch (ir.TransactionCode)
                                                {
                                                    case "OK":
                                                        t.Status = (int)TransactionStatuses.Completed;

                                                        ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
                                                        ro.Description = ir.txtDescription;
                                                        ro.TransactionCode = t.TransactionCode;
                                                        Log.WriteInformation(61285219, "Transaction Successful, Voucher Number: " + PIN + " by UserId =" + UserAccount.Id.ToString());
                                                        
                                                        break;
                                                    case "NOK":
                                                        t.Status = (int)TransactionStatuses.Denied;
                                                        ro.ResponseCode = (int)TransactionStatuses.Denied;
                                                        ro.Description = ir.txtDescription;
                                                        break;
                                                    default:
                                                        t.Status = (int)TransactionStatuses.Cancelled;
                                                        ro.ResponseCode = Convert.ToInt32(ir.TransactionCode);
                                                        ro.Description = ir.errDescription;
                                                        break;

                                                }
                                                //Transaction added to the DB
                                                t = actions.AddTransaction(t);
                                            break;

                                        default:
                                            // add exception code here around voucher type
                                                ro.ResponseCode = (int)ResponseCodes.InvalidVoucher;
                                                ro.Description = "Unknown Voucher Type";
                                                rv.ro = ro;
                                                d.Clear();
                                                d.Add("Voucher Details ", PIN);
                                                d.Add("Partner Username", Username);
                                                d.Add("Voucher Type Id", VoucherType.ToString());
                                                Log.WriteInformation(21756462, "Unknown Voucher Type, Fraud Suspected ", d);
                                            break;
                                    }

                                    
                                   
                                }

                            }                  
                        			
            }
            else
            {
                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please Contact MMIT";
            
                d.Clear();
                d.Add("Username ",  Username );
                d.Add("Password ", Password);
                Log.WriteInformation(4533455, "Invalid Username or Password ", d);
            }

            rv.ro = ro;
            return rv;
            
            }
            catch (Exception e)
            {
                Log.WriteCritical(901, e);

                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please Contact Customer Service";
                rv.ro = ro;
                return rv;
            }
           
		}

		
        
        public QueryTransaction QueryTransaction(string token)
		{
            QueryTransaction qt = new QueryTransaction();
            try
            {
            //Add logging of where request originates from
            d.Clear();
            d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
            d.Add("Method :", "QueryTransaction");
            Log.WriteInformation(446389, "Originating IP and Port", d);


			
			Transaction t = actions.CheckTransaction(token);
			if (t != null)
			{
				switch (t.Status)
				{
					case (int)TransactionStatuses.Pending:
						d.Clear();
						d.Add("Valid Transaction for Withdrawal Display ", Log.Desc(t));
						Log.WriteInformation(643453822, "Valid Transaction", d);
						

						Account UserAccount = actions.GetAccount(t.RecipientId);
						Customer Cust = actions.GetCustomer(UserAccount.CustomerId);

						//qt.Transaction = t;
						//qt.Customer = Cust;
						Transaction lt = new Transaction();
						Customer lc = new Customer();
						lt.Amount = t.Amount;
						lt.ParentId = t.ParentId;
						lt.Id = t.Id;
						lt.Status = t.Status;
						lt.TimeInitiated = t.TimeInitiated;
						qt.Transaction = lt;

						lc.Mobile = Cust.Mobile;
						qt.Customer = lc;

                        
						
						ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
						ro.Description = "Valid Transaction in Correct State";
						break;

					default:
						ro.ResponseCode = (int)ResponseCodes.SystemError;
						ro.Description = "This Transaction is in an Invalid State";
						d.Clear();
						d.Add("Flouted Rule ", Log.Desc(t));
						Log.WriteInformation(643453222, "Fraud Suspected", d);
						break;
						
				}
			}
			else
			{
				ro.ResponseCode = (int)ResponseCodes.TransactionNotFound;
				ro.Description = "Transaction Does Not Exist ";
				d.Clear();
				d.Add("Invalid Token ", token);
				Log.WriteInformation(643123222, "Non Existent Transaction", d);

			}

			qt.ro = ro;
			return qt;

            }
            catch (Exception e)
            {
                Log.WriteCritical(901, e);

                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please Contact Customer Service";
                qt.ro = ro;
                return qt;
            }
		}

        public TransactionCharges GetTransactionCharges(decimal txnAmount, int transactionType)
        {
            TransactionCharges tc = new TransactionCharges();
            TransactionCharge ch;
            Charge chg;
            try
            {
                //Add logging of where request originates from
                d.Clear();
                d.Add("Originating IP and Port", shared.OriginatingIP_Port(OperationContext.Current));
                d.Add("Method :", "GetTransactionCharges");
                Log.WriteInformation(4543389, "Originating IP and Port", d);

                List<TransactionCharge> TxnCharges = new List<TransactionCharge>();
                List<TransactionCharge> TxnCharges_AmountOnly = new List<TransactionCharge>();


                TxnCharges = actions.CalculateCharges(transactionType, txnAmount);
                ro.ResponseCode = (int)ResponseCodes.TransactionSuccessful;
                if (TxnCharges.Count > 0)
                {
                    foreach (var c in TxnCharges)
                    {
                        chg = new Charge();
                        chg.Name = c.Charge.Name;
                        chg.PercentageAmount = c.Charge.PercentageAmount;
                        chg.MinAmount = c.Charge.MinAmount;
                        chg.MaxAmount = c.Charge.MaxAmount;
                        chg.FixedAmount = c.Charge.FixedAmount;

                        ch = new TransactionCharge();
                        ch.Amount = c.Amount;
                        ch.Charge = chg;

                        TxnCharges_AmountOnly.Add(ch);

                    }
                    tc.txnCharges = TxnCharges_AmountOnly;
                    ro.Description = "Charges Calculated for :Amount - " + txnAmount.ToString() + " Txn Type - " + transactionType.ToString();
                }
                else
                {
                    ro.Description = "No Charges for :Amount - " + txnAmount.ToString() + " Txn Type - " + transactionType.ToString();
                }

                ro.TransactionCode = TxnCharges.Count.ToString();
                tc.ro = ro;

            }
            catch (Exception e)
            {
                Log.WriteCritical(645321, e);
                ro.ResponseCode = (int)ResponseCodes.SystemError;
                ro.Description = "Please contact MMIT Customer Service.";
                tc.ro = ro;

            }


            return tc;

        }
		
	}
}
